package com.cy.study.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cy.study.Enum.PlanSituationEnum;
import com.cy.study.Enum.PlanStatusEnum;
import com.cy.study.Enum.PushTypeEnum;
import com.cy.study.Enum.UserSeeEnum;
import com.cy.study.common.BasePageReq;
import com.cy.study.entity.NewsEntity;
import com.cy.study.entity.PushRecordEntity;
import com.cy.study.entity.UserInfoEntity;
import com.cy.study.entity.UserPlanEntity;
import com.cy.study.exception.BusinessException;
import com.cy.study.mapper.NewsMapper;
import com.cy.study.mapper.PushRecordMapper;
import com.cy.study.mapper.UserInfoMapper;
import com.cy.study.mapper.UserPlanMapper;
import com.cy.study.req.AddPushReq;
import com.cy.study.req.HandlePushPlanReq;
import com.cy.study.req.PushPageReq;
import com.cy.study.res.PushDetailRes;
import com.cy.study.res.PushPageRes;
import com.cy.study.res.UserCenterPagePushRes;
import com.cy.study.res.UserCenterPushDetailRes;
import com.cy.study.service.NewsService;
import com.cy.study.service.PushRecordService;
import com.cy.study.service.UserInfoService;
import com.cy.study.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class PushRecordServiceImpl extends ServiceImpl<PushRecordMapper, PushRecordEntity> implements PushRecordService {

    private final NewsMapper newsMapper;
    private final UserInfoMapper userInfoMapper;
    private final UserPlanMapper userPlanMapper;

    @Override
    public Page<PushPageRes> pagePush(PushPageReq req) {
        Page page = new Page(req.getPageNum(),req.getPageSize());
        Page<PushPageRes> res = this.getBaseMapper().pagePush(req,page);
        return res;
    }

    @Override
    public void handlePushPlan(HandlePushPlanReq req) {
        if(req.getNewsId()==null){
            throw new BusinessException("资讯id不能为空");
        }
        if(req.getMajorIds()==null||req.getMajorIds().size()==0){
            throw new BusinessException("专业ids不能为空");
        }
        QueryWrapper<UserInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(UserInfoEntity::getMajorId,req.getMajorIds());
        List<UserInfoEntity> users = userInfoMapper.selectList(wrapper);
        List<PushRecordEntity> res = new ArrayList<>(users.size());
        users.stream().forEach(e->{
            PushRecordEntity record = new PushRecordEntity();
            record.setPushType(PushTypeEnum.UNAUTO.getValue());
            NewsEntity news = newsMapper.selectById(req.getNewsId());
            record.setTitle(news.getTitle());
            record.setRelationId(req.getNewsId());
            record.setMessage("有一条有关于您的资讯推送，推送标题:《"+news.getTitle()+"》,请及时查看");
            record.setStatus(UserSeeEnum.NO.getValue());
            record.setCreateTime(LocalDateTime.now());
            record.setUserId(e.getId());
            res.add(record);
        });
        this.saveOrUpdateBatch(res);
    }

    @Override
    public void autoPushPlan() {
        QueryWrapper<UserPlanEntity> planWrapper = new QueryWrapper<>();
        planWrapper.lambda().
                eq(UserPlanEntity::getStatus, PlanStatusEnum.ING.getValue());
        List<UserPlanEntity> plans = userPlanMapper.selectList(planWrapper);
        List<PushRecordEntity> res = new ArrayList<>(plans.size());
        plans.stream().forEach(e->{
            //处理计划状态
            handlePlanStatus(e);
            PushRecordEntity record = new PushRecordEntity();
            record.setTitle("个人计划推送");
            record.setPushType(PushTypeEnum.AUTO.getValue());
            record.setMessage("有一条有关于个人计划进度的推送，推送标题:《"+e.getPlanName()+"》,请及时查看");
            record.setStatus(UserSeeEnum.NO.getValue());
            record.setCreateTime(LocalDateTime.now());
            record.setUserId(e.getUserId());
            res.add(record);
        });
        this.saveOrUpdateBatch(res);
    }

    @Override
    public PushDetailRes detail(Integer pushRecordId) {
        PushRecordEntity record = this.getById(pushRecordId);
        UserInfoEntity entity = userInfoMapper.selectById(record.getUserId());
        PushDetailRes res = new PushDetailRes();
        BeanUtils.copyProperties(record,res);
        res.setUserName(entity==null?null:entity.getName());
        return res;
    }

    @Override
    public Page<UserCenterPagePushRes> userCenterPagePush(BasePageReq req) {
            Integer userId = SecurityUtils.getUserId();
            Page page = new Page(req.getPageNum(),req.getPageSize());
            QueryWrapper<PushRecordEntity> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(PushRecordEntity::getUserId,userId)
                    .orderByDesc(PushRecordEntity::getCreateTime);
            Page info =  this.getBaseMapper().selectPage(page,wrapper);
        List<PushRecordEntity> records = info.getRecords();
        List<UserCenterPagePushRes> res = new ArrayList<>();
        records.stream().forEach(e->{
            UserCenterPagePushRes temp = new UserCenterPagePushRes();
            BeanUtils.copyProperties(e,temp);
            res.add(temp);
        });
        info.setRecords(res);
        return info;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserCenterPushDetailRes userCenterPushDetail(Integer pushId) {
        PushRecordEntity record = this.getById(pushId);
        record.setStatus(1);
        this.saveOrUpdate(record);
        UserCenterPushDetailRes res = new UserCenterPushDetailRes();
        BeanUtils.copyProperties(record,res);
        return res;
    }


    private void handlePlanStatus(UserPlanEntity entity){
        LocalDateTime now = LocalDateTime.now();
        Double taskDaysBetween = Double.valueOf(ChronoUnit.DAYS.between(entity.getCreateTime(), entity.getEndTime()));
        Double truth = Double.valueOf(ChronoUnit.DAYS.between(entity.getCreateTime(), now));
        if(truth*100.0/taskDaysBetween>entity.getCurrentFinishPercent()){
            if((truth*100.0/taskDaysBetween-20)>entity.getCurrentFinishPercent()){
                entity.setSituation(PlanSituationEnum.WARN.getValue());
            }else {
                entity.setSituation(PlanSituationEnum.PRESSING.getValue());
            }
        }else {
            entity.setSituation(PlanSituationEnum.NORMAL.getValue());
        }
        userPlanMapper.updateById(entity);
    }
}
